package com.javadaemon.rpgengine.model;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import org.newdawn.slick.SlickException;

import com.javadaemon.rpgengine.screens.MapScreen;
import com.javadaemon.rpgengine.screens.Screen;
import com.javadaemon.rpgengine.util.MapLoader;
import com.javadaemon.rpgengine.util.ResourceManager;
import com.javadaemon.rpgengine.util.ResourceManager.ANIMATION_SET;


/*
 Copyright (c) 2011, Morten Andersen
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:
 * Redistributions of source code must retain the above copyright
 notice, this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 notice, this list of conditions and the following disclaimer in the
 documentation and/or other materials provided with the distribution.
 * The name of the author may not be used to endorse or promote products
 derived from this software without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL MORTEN ANDERSEN BE LIABLE FOR ANY
 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * This class encapsulates all data and state information used in the game, as
 * well as methods for reading and changing these. Having all data in one place,
 * makes it easier to implement savegame functionality at a later time, and
 * ensures that all data queries from the game logic and user interfaces
 * accesses the game data in a similar way. The seperation is not completely
 * clean yet, since information about which GUIs and maps to use are also kept
 * as part of the game state (it would probably not be very useful to actually
 * save the game map and gui information as part of a save game). This is done
 * for simplicity's sake. At a later point, the GameState class will be further
 * subdivided into "general game state" and "save game state".
 * 
 * @author Somnium
 * 
 */
public class GameState
{

	/**
	 * This enum contains the different types of GUIs used by the application.
	 */
	public enum SCREEN
	{
		TITLE, // TODO Implement later
		MAP, // The main map interface, where the world is navigated.
		COMBAT, // TODO Implement later
		;
	}

	private Screen activeScreen; // The currently active GUI
	private Map<SCREEN, Screen> screens; // All GUIs used by the application,
											// mapped to a reference key.
	private Map<String, TileMap> maps; // All TileMap instances used by the
										// application, mapped to a reference
										// key. A String is used rather than an
										// enum, to allow for a more dynamic
										// handling of maps.
	private ArrayList<Actor> characters; // All characters in the game
	private Actor player; // The Actor instance representing the player avatar.
	private final int scaleModifier = 2; // The modifier of which the game shall
											// be scaled

	public Screen getActiveScreen()
	{
		return activeScreen;
	}

	/**
	 * Constructor - calling this also initializes the game state.
	 * 
	 * @throws SlickException
	 * @throws IOException 
	 */
	public GameState() throws SlickException
	{
		initGame();
	}

	/**
	 * Initializes the game state for a new game. This method is public, to
	 * allow a GUI to start a new game.
	 * 
	 * @throws SlickException
	 * @throws IOException 
	 */
	public void initGame() throws SlickException
	{
		// Init screens
		screens = new HashMap<SCREEN, Screen>();
		screens.put(SCREEN.MAP, new MapScreen(this));

		// Init maps
		maps = new HashMap<String, TileMap>();
		TileMap map = MapLoader
				.createMap(ResourceManager.MAP.MAP001);
		
		maps.put("map001", map);
		
		// Init characters
		Actor character = new Actor(12, 15, "map001", ResourceManager
				.getRessourceManager().getAnimationSet(
						ANIMATION_SET.CHARACTER_ANIMATIONS));
		map.getTile(12, 15).setActor(character);

		// Init player
		player = new Actor(10, 10, "map001", ResourceManager
				.getRessourceManager().getAnimationSet(
						ANIMATION_SET.PLAYER_ANIMATIONS));
		map.getTile(10, 10).setActor(player);
		
		activeScreen = screens.get(SCREEN.MAP);
	}

	public Map<String, TileMap> getMaps()
	{
		return maps;
	}

	public Actor getPlayer()
	{
		return player;
	}
	
	public TileMap getMap(String mapId)
	{
		return maps.get(mapId);
	}

	public int getScale()
	{
		return scaleModifier;
	}
}